import React, { useState, useContext, useImperativeHandle, useRef, forwardRef, useEffect } from 'react'
import "./index.scss";
import { deepCopy } from "../../../utils/common";

interface itemType {
    title: string,
    id: string,
    toggle?: boolean,
    active: boolean,
    children?: itemType[]
}

interface defaultProps {
    titleKey?: string,  // 传来数据显示标题的字段
    idKey?: string, //传来数据的id的字段
    activeKey?: string, // 传来数据选中的字段
    childrenKey?: string   // 传来数据子集的字段
    data: itemType[],
    layer?: number, //第几层
    gap?: number,
    path?: number[], // 每一级的索引数组
    onCheck?: Function //点击每个checkbox返回数据列表
}

/**
 * 
 *  可接受的数据格式
 * 
 *  [
 *    {
 *       title:"全选",
 *       id:"-1",
 *       toggle:true, // 闭合还是打开
 *       active:false, // 选中还是不选中
 *       children:[
 *           {
 *               title:"供应链",
 *               id:"1",
 *               children:[],
 *               toggle:false, //有children属性才会toggle,没有children属性说明没有后代
 *               active:false, // 选中还是不选中   
 *           }   
 *       ]
 *    }
 *  ]  
 * 
 * 
 */

/**
 * 渲染左侧
 */
const renderLeft = (item: itemType) => {
    // 有子集吗  
    if (item.children) {
        if (item.toggle) { //打开状态
            return <svg key="1" viewBox="0 0 1024 1024" focusable="false" data-icon="caret-down" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"></path></svg>
        } else { //关闭状态
            return (<div className="close">
                <svg key="1" viewBox="0 0 1024 1024" focusable="false" data-icon="caret-down" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"></path></svg>
            </div>)
        }
    } else {
        return <div className="pp"><path d="M832 112H724V72c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v40H500V72c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v40H320c-17.7 0-32 14.3-32 32v120h-96c-17.7 0-32 14.3-32 32v632c0 17.7 14.3 32 32 32h512c17.7 0 32-14.3 32-32v-96h96c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zM664 888H232V336h218v174c0 22.1 17.9 40 40 40h174v338zm0-402H514V336h.2L664 485.8v.2zm128 274h-56V456L544 264H360v-80h68v32c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-32h152v32c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-32h68v576z"></path></div>//<svg viewBox="64 64 896 896" focusable="false" data-icon="snippets" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 112H724V72c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v40H500V72c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v40H320c-17.7 0-32 14.3-32 32v120h-96c-17.7 0-32 14.3-32 32v632c0 17.7 14.3 32 32 32h512c17.7 0 32-14.3 32-32v-96h96c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zM664 888H232V336h218v174c0 22.1 17.9 40 40 40h174v338zm0-402H514V336h.2L664 485.8v.2zm128 274h-56V456L544 264H360v-80h68v32c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-32h152v32c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-32h68v576z"></path></svg>
    }
}

/**
 * 拿到当前级别的state
 */
const getNestState = (rootState: itemType[], path: number[]) => {
    path.shift(); //使用了 rootState[0] , 第一个 0 就要排除
    const array: itemType[] = [];
    path.reduce((cur: any, next: number) => {
        const cur_item = cur.children[next];
        array.push(cur_item);
        return cur_item;
    }, rootState[0])
    if (array.length == 0) {
        return rootState;
    }
    return array;
}


const treeContext = React.createContext<any>(null);

interface funcType {
    titleKey?: string,
    idKey?: string,
    activeKey?: string,
    childrenKey?: string
    layer: number,
    gap: number,
    source: itemType[],
    path: number[],
    onCheck?: Function
}


export const ControllTree = React.forwardRef((props: funcType, ref) => {

    const { source: data, onCheck, titleKey = 'title', activeKey = 'active', idKey = 'id', childrenKey = "children" } = props;
    const clone_data = deepCopy(data)

    const dataChange = (arr:any,isALLCheck:any)=>{
        /**
         * 通过递归将数据的字段根据
         * titleKey，
         * idKey，
         * activeKey，
         * childrenKey的值
         * 重置为
         * {
         *     title:'',
         *     id:'',
         *     active:boolean, 
         *     toggle:boolean,
         *     children:[]
         * }
         */
 
       return arr.map((val:any)=>{
           if(!!val[activeKey]==false){
            isALLCheck.isALLCheck = false
           }
            val['title'] = val[titleKey]
            delete val[titleKey]
            val['id'] = val[idKey]
            delete val[idKey]
            val['active'] = !!val[activeKey]
            delete val[activeKey]
            val['toggle'] = true
            if(val[childrenKey]){
                val['children'] = val[childrenKey]
                if(val[childrenKey].length>0){
                    dataChange(val[childrenKey],isALLCheck)
                    delete val[childrenKey]
                }else{
                delete val[childrenKey]
                delete val.children
                }
            }
            return val
        })
    }
    const formatChange = (data: any) => {
        let isALLCheck = {isALLCheck:true}
        const normal_data = dataChange(data,isALLCheck)
        const new_data = [{
            title: '全选',
            id: '-1',
            active: isALLCheck.isALLCheck,
            toggle: true,
            children: []
        }]
        new_data[0].children = normal_data
        return new_data
    }

    const new_data = formatChange(clone_data)

    const source = new_data; // 更换成新的数据源


    const [tree_data, updataData] = useState(source);

    const updateTreeData = (array: number[], callback: Function) => { // 更新根数据
        const new_data = deepCopy(tree_data);
        if (new_data == null) {
            return;
        }
        const list = getNestState(new_data, array);
        const flag = callback(list);
        if (!flag) {
            updataData(new_data);
        }
        return Promise.resolve();
    }

    /**
     * 将计算的数据返回回去
     */
    const onCheckFn = (flag = false) => {

        const source = tree_data;

        if (!flag && !onCheck) {
            return;
        }
        const array: string[] = [];
        const circute = (data: itemType[]) => {
            data.forEach((child) => {
                if (child.active) {
                    array.push(child.id);
                }
                if (child.children) {
                    circute(child.children);
                }
            })
        }
        circute(source);
        if (flag) {
            return array;
        }
        if (onCheck) {
            onCheck(array);
        }
    }


    useImperativeHandle(ref, () => ({
        getData: () => {
            const result = onCheckFn(true);
            if (!result) {
                return [];
            }
            const index = result.indexOf("-1");
            if (index != -1) {
                result.splice(index, 1);
            }
            return result;
        }
    }));
    return (
        <treeContext.Provider value={{ updateTreeData, onCheck: onCheckFn }}>
            <Jsx {...props} source={tree_data} />
        </treeContext.Provider>
    )

})


/**
 *  返回的DOM
 */
const Jsx = ({ layer, gap, source, path }: funcType) => {
    const { updateTreeData: treeHandler, onCheck } = useContext(treeContext);

    //打开/收起 
    const toggleItem = (index: number) => {
        const excuate = (list: itemType[]) => {
            const parent = list[list.length - 1];
            if (parent == null || parent.children == null) {
                return;
            }
            const item = layer == 0 ? parent : parent.children[index];
            if (item.children == null) {
                return "stop";
            }
            item.toggle = !item.toggle;
        }
        treeHandler(path, excuate);
    }

    const onChange = async (index: number) => {
        const excuate = (list: itemType[]) => {
            const parent = list[list.length - 1];
            if (parent == null || parent.children == null) {
                return;
            }
            const item = layer == 0 ? parent : parent.children[index];
            item.active = !item.active;
            //循环调用
            const circute = (ob: itemType) => {
                ob.children?.forEach((child) => {
                    child.active = item.active;
                    circute(child);
                })
            }
            circute(item);
            if (item.active) {
                list.forEach((item) => {
                    if (item.id != "-1") {
                        item.active = true;
                    }
                })
            }
        }
        await treeHandler(path, excuate);
        onCheck(source);
    }
    return (
        <div className="Tree" style={{ marginLeft: `${layer * gap}px` }}>
            {
                source.map((item, index) => {
                    return (
                        <div className="wrapper" key={index}>
                            <div className="line">
                                <div className="icon" onClick={() => { toggleItem(index) }}>{renderLeft(item)}</div>
                                <div className="check-input">
                                    <input type="checkbox" checked={item.active} onChange={() => { onChange(index) }} />
                                </div>
                                <div className="tits">
                                    {item.title}
                                </div>
                            </div>
                            {
                                item.children && item.toggle ?
                                    <TreeInstance data={item.children} layer={layer + 1} path={[...path, index]} />
                                    : null
                            }
                        </div>
                    )
                })
            }
        </div>
    )
}


const TreeInstance = (props: defaultProps, ref: any) => {
    const { data = [], layer = 0, gap = 25, path = [], onCheck, titleKey = 'title', activeKey = 'active', idKey = 'id', childrenKey = "children" } = props;
    const params = {
        path,
        gap,
        layer,
        source: data,
        titleKey,
        activeKey,
        idKey,
        childrenKey,
    }

    //只有在第0层时才整体深拷贝数据源
    if (layer === 0) {
        return <ControllTree {...params} onCheck={onCheck} ref={ref} />
    } else {
        return <Jsx {...params} />
    }
}

const Tree = React.forwardRef(TreeInstance);

export default Tree;